home *** CD-ROM | disk | FTP | other *** search
/ MIDICraft's MIDINET CD-ROM / MIDICraft's MIDINET CD-ROM.iso / DOSUTILS / TXT2MIDI.ZIP / MIDIREAD.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-11  |  6.6 KB  |  325 lines

  1. // midiread v1.0 written by Günter Nagler 1995 (gnagler@ihm.tu-graz.ac.at)
  2. #include "midiread.hpp"
  3.  
  4. unsigned long getlong(FILE* f)
  5. {
  6. unsigned char c[4];
  7. unsigned long n = 0;
  8.  
  9.   if (fread(c, 4, 1, f) != 1)
  10.     return 0;
  11.   n = c[0];
  12.   n = (n << 8) + c[1];
  13.   n = (n << 8) + c[2];
  14.   n = (n << 8) + c[3];
  15.   return n;
  16. }
  17.  
  18. unsigned long gettri(FILE* f)
  19. {
  20. unsigned char c[3];
  21. unsigned long n = 0;
  22.  
  23.   if (fread(c, 3, 1, f) != 1)
  24.     return 0;
  25.   n = c[0];
  26.   n = (n << 8) + c[1];
  27.   n = (n << 8) + c[2];
  28.   return n;
  29. }
  30.  
  31. int getbyte(FILE*f)
  32. {
  33.   return fgetc(f);
  34. }
  35.  
  36. void putbyte(FILE* f, int n)
  37. {
  38.   fputc(n, f);
  39. }
  40.  
  41. unsigned short getword(FILE* f)
  42. {
  43. unsigned char c[2];
  44. unsigned short n = 0;
  45.  
  46.   if (fread(c, 2, 1, f) != 1)
  47.     return 0;
  48.   n = c[0];
  49.   n = (n << 8) + c[1];
  50.   return n;
  51. }
  52.  
  53. void putword(FILE* f, unsigned short n)
  54. {
  55. unsigned char c[2];
  56.  
  57.   c[0] = ((n>>8) & 0xff);
  58.   c[1] = n & 0xff;
  59.   fwrite(c, 2, 1, f);
  60. }
  61.  
  62. void putlong(FILE* f, unsigned long n)
  63. {
  64. unsigned char c[4];
  65.  
  66.   c[0] = ((n>>24) & 0xff);
  67.   c[1] = ((n>>16) & 0xff);
  68.   c[2] = ((n>>8) & 0xff);
  69.   c[3] = n & 0xff;
  70.   fwrite(c, 4, 1, f);
  71. }
  72.  
  73. void puttri(FILE* f, unsigned long n)
  74. {
  75. unsigned char c[3];
  76.  
  77.   c[0] = ((n>>16) & 0xff);
  78.   c[1] = ((n>>8) & 0xff);
  79.   c[2] = n & 0xff;
  80.   fwrite(c, 3, 1, f);
  81. }
  82.  
  83. int get_midihead(FILE* f, MIDIHEAD* h)
  84. {
  85. long tag;
  86. long taglen;
  87. long tagend;
  88.  
  89.   fseek(f, 0L, SEEK_SET);
  90.  
  91.   tag = getlong(f);
  92.   if (tag != MThd)
  93.     return 0;
  94.  
  95.   taglen = getlong(f);
  96.   tagend = ftell(f)+taglen;
  97.  
  98.   h->songs = getword(f);
  99.   h->tracks = getword(f);
  100.   h->unitsperbeat = getword(f);
  101.   fseek(f, tagend, SEEK_SET);
  102.  
  103.   return 1;
  104. }
  105.  
  106. void skip_tag(FILE* f)
  107. {
  108.   getlong(f);
  109.   fseek(f, getlong(f), SEEK_CUR);
  110. }
  111.  
  112. void put_midihead(FILE* f, MIDIHEAD* h)
  113. {
  114.   fseek(f, 0L, SEEK_SET);
  115.  
  116.   putlong(f, MThd);
  117.   putlong(f, 6l);
  118.  
  119.   putword(f, h->songs);
  120.   putword(f, h->tracks);
  121.   putword(f, h->unitsperbeat);
  122. }
  123.  
  124. unsigned long getdelta(FILE* f)
  125. {
  126. unsigned long n = 0;
  127. int i = 0, c;
  128.  
  129.   for (i = 0; i < 4; i++)
  130.   {
  131.     c = fgetc(f);
  132.     if (c == -1)
  133.       break;
  134.     n = (n << 7) + (c & 0x7f);
  135.     if ((c & 0x80) == 0)
  136.       break;
  137.   }
  138.   return n;
  139. }
  140.  
  141. void putdelta(FILE* f, unsigned long n)
  142. {
  143. unsigned char c[4], v;
  144. int i = 0;
  145.  
  146.   while (i < 4)
  147.   {
  148.     v = n & 0x7f;
  149.     n >>= 7;
  150.     c[i++] = v;
  151.     if (n == 0)
  152.       break;
  153.   }
  154.   while (i > 0)
  155.   {
  156.   int v;
  157.  
  158.     v = c[--i];
  159.     if (i > 0)
  160.       v |= 0x80;
  161.     fputc(v, f);
  162.   }
  163. }
  164.  
  165. static long chunkpos;
  166.  
  167. void open_chunk(FILE* f, char* s)
  168. {
  169.   fwrite(s, 1, 4, f);
  170.   putlong(f, 0L);
  171.   chunkpos = ftell(f);
  172. }
  173.  
  174. void close_chunk(FILE* f)
  175. {
  176. unsigned long p = ftell(f);
  177. unsigned long len = 0;
  178.  
  179.   len = p - chunkpos;
  180.   fseek(f, chunkpos-4, SEEK_SET);
  181.   putlong(f, len);
  182.   fseek(f, p, SEEK_SET);
  183. }
  184.  
  185. int scanevent(
  186.   FILE* f,
  187.   unsigned long* dtime,
  188.   unsigned char* ev,
  189.   unsigned char lastev,
  190.   unsigned long* len)
  191. {
  192. int c;
  193.  
  194.   *dtime = getdelta(f);
  195.   c = getbyte(f);
  196.  
  197.   if (c == EOF)
  198.     return 0;
  199.  
  200.   if ((c & 0x80) == 0 && (lastev >= 0x80 && lastev <= 0xEF))
  201.   {
  202.     fseek(f, -1, SEEK_CUR);  // event not given, use lastev
  203.     c = lastev;
  204.   }
  205.   *ev = c;
  206.   switch(c & 0xf0)
  207.   {
  208.   case 0xf0:
  209.     {
  210.       switch(c)
  211.       {
  212.       case 0xf0: // sysex event
  213.     *len = getdelta(f);
  214.     break;
  215.       case 0xf2:  // song position pointer event
  216.     *len = 2;
  217.     break;
  218.       case 0xf3:  // song select event
  219.     *len = 1;
  220.     break;
  221.       case 0xf6:  // tune request event
  222.       case 0xf8:  // timing clock event
  223.       case 0xfa:  // start event
  224.       case 0xfb:  // continue event
  225.       case 0xfc:  // stop event
  226.       case 0xfe:  // active sensing event
  227.     *len = 0;
  228.     break;
  229.       case 0xff:  // system reset event
  230.     {
  231.     long p = ftell(f);
  232.  
  233.       getbyte(f);
  234.       *len = getdelta(f);
  235.       *len += ftell(f)-p;
  236.       fseek(f, p, SEEK_SET);
  237.     }
  238.       }
  239.     }
  240.     break;
  241.   case 0x90: // notes
  242.   case 0x80:
  243.       *len = 2;
  244.       break;
  245.   case 0xC0:
  246.   case 0xD0:
  247.     *len = 1;
  248.     break;
  249.   case 0xA0:
  250.   case 0xB0:
  251.   case 0xE0:
  252.     *len = 2;
  253.     break;
  254.   default:
  255.     *len = 0;
  256.     return 0;
  257.   }
  258.   return 1;
  259. }
  260.  
  261. int seekchannel(FILE* f, unsigned long len)
  262. {
  263. unsigned char lastev = 0xff, ev;
  264. long oldpos = ftell(f);
  265. long endpos = oldpos + len;
  266. unsigned long delta, paramlen;
  267.  
  268.   while (ftell(f) < endpos && scanevent(f, &delta, &ev, lastev, ¶mlen) && !feof(f))
  269.   {
  270.     if (ev >= 0x80 && ev <= 0xEF)
  271.     {
  272.       fseek(f, oldpos, SEEK_SET);
  273.       return ev & 15;
  274.     }
  275.     fseek(f, paramlen, SEEK_CUR);
  276.   }
  277.   fseek(f, oldpos, SEEK_SET);
  278.   return -1;
  279. }
  280.  
  281. static char* GMProg[128] =
  282. {
  283.   "Piano", "BritePiano", "HammerPiano", "HonkeyTonk", "NewTines", "DigiPiano", "Harpsicord", "Clav",
  284.   "Celesta", "Glocken", "MusicBox", "Vibes", "Marimba", "Xylophon", "Tubular", "Santur",
  285.   "FullOrgan", "PercOrgan", "BX-3Organ", "ChurchPipe", "Positive", "Musette", "Harmonica", "Tango",
  286.   "ClassicGtr", "A.Guitar", "JazzGuitar", "CleanGtr", "MuteGuitar", "OverDrive", "DistGuitar", "RockMonics",
  287.   "JazzBass", "DeepBass", "PickBass", "FretLess", "SlapBass1", "SlapBass2", "SynthBass1", "SynthBass2",
  288.   "Violin", "Viola", "Cello", "ContraBass", "TremoloStr", "Pizzicato", "Harp", "Timpani",
  289.   "Marcato", "SlowString", "AnalogPad", "StringPad", "Choir", "DooVoice", "Voices", "OrchHit",
  290.   "Trumpet", "Trombone", "Tuba", "MutedTrumpet", "FrenchHorn", "Brass", "SynBrass1", "SynBrass2",
  291.   "SopranoSax", "AltoSax", "TenorSax", "BariSax", "SweetOboe", "EnglishHorn", "BasoonOboe", "Clarinet",
  292.   "Piccolo", "Flute", "Recorder", "PanFlute", "Bottle", "Shakuhachi","Whistle", "Ocarina",
  293.   "SquareWave", "SawWave", "SynCalinope", "SynChiff", "Charang", "AirChorus", "Rezzo4ths", "Bass&Lead",
  294.   "Fantasia", "WarmPad", "PolyPad", "GhostPad", "BowedGlas", "MetalPad", "HaloPad", "Sweep",
  295.   "IceRain", "SoundTrack", "Crystal", "Atmosphere", "Brightness", "Goblin", "EchoDrop", "StarTheme",
  296.   "Sitar", "Banjo", "Shamisen", "Koto", "Kalimba","Scotland","Fiddle", "Shanai",
  297.   "MetalBell", "Agogo", "SteelDrums", "Woodblock", "Taiko", "Tom", "SynthTom", "RevCymbal",
  298.   "FretNoise", "NoiseChiff", "Seashore", "Birds", "Telephone", "Helicopter", "Stadium!!", "GunShot"
  299. };
  300.  
  301. const char* progname(int n, int channel)
  302. {
  303. static char defname[10] = "";
  304.  
  305.   if (channel == 9) // drum programs
  306.   {
  307.     switch(n)
  308.     {
  309.     case 0:    return "Dr1";
  310.     case 0x10: return "Dr2";
  311.     case 0x19: return "Dr3";
  312.     case 0x20: return "Dr4";
  313.     case 0x28: return "Dr5";
  314.     case 0x40: return "Dr6";
  315.     case 0x18: return "Dr7";
  316.     case 0x30: return "Dr8";
  317.     }
  318.   }
  319.   else if (n >= 0 && n <= 127)
  320.     return GMProg[n];
  321. def:
  322.   sprintf(defname, "%d", n);
  323.   return (const char*)defname;
  324. }
  325.